/*
 * ============================================================================
 *
 *       Filename:  main.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2013年09月26日 15时55分31秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  jianxi sun (jianxi), ycsunjane@gmail.com
 *   Organization:  
 *
 * ============================================================================
 */
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

static int is_hex(int c)
{
	if((c >= 0x30) && (c <= 0x39))
		return 1;
	if((c >= 0x41) && (c <= 0x46))
		return 1;
	if((c >= 0x61) && (c <= 0x66))
		return 1;
	return 0;
}

static int get_ip_sec(char *str, char **next_ptr)
{
	long ana; 
	ana = strtoul(str, next_ptr, 16);
	switch(**next_ptr) {
	case '.': case ':': case 0:
		return ana;
	default:
		return -1;
	}
}

int global_cross = 0;
#define GLOBAL_ACROSS_BEGIN 	(1 << 0)

#define ACROSS_ON 		(1 << 0)
#define ACROSS_BEGIN 		(1 << 1)
#define ACROSS_END 		(1 << 2)
#define HAVE_ACROSS_ON 		(1 << 3)
#define ACROSS_ENDON 		(1 << 4)

static int is_set(int status, int param)
{
	return status & param;
}

static void set_flag(int *status, int param)
{
	*status |= param; 
}

static void clr_flag(int *status, int param)
{
	*status &= ~param; 
}

static int ana_ip(char *sip, char *dip, char *buf, int proc_num, int pre_across, int mode, char *buf_head)
{
	if(proc_num == 0) {
		printf("%s\n", buf_head);
		return 0;
	}

	int out_len = 0;

	/* analyse sip, get first section int value */
	char *s_next_ptr, *d_next_ptr;
	int s_sct, d_sct;
	s_sct = get_ip_sec(sip, &s_next_ptr);
	d_sct = get_ip_sec(dip, &d_next_ptr);
	if((s_sct == -1) || (d_sct == -1))
		return -1;

	/* process equal */
	if((s_sct == d_sct) && !is_set(global_cross, GLOBAL_ACROSS_BEGIN) && mode != 1) {
		out_len = sprintf(buf, "\\x%x", s_sct);
		ana_ip(s_next_ptr + 1, d_next_ptr + 1, buf + out_len, proc_num-1, 0, mode, buf_head);
		*(buf + out_len) = 0;
		return 0;
	}

	int ret;
	if(is_set(global_cross, GLOBAL_ACROSS_BEGIN)) {
		while(s_sct <= 255) {
			if(is_set(pre_across, ACROSS_BEGIN)) {
				if(proc_num != 1) {
					out_len = sprintf(buf, "\\x%x", s_sct);
				} else {
					out_len = sprintf(buf, "[\\x%x-\\x%x]", s_sct, 255);
					s_sct = 255;
				}
			}

			if(is_set(pre_across, HAVE_ACROSS_ON)) {
				out_len = sprintf(buf, "[\\x%x-\\x%x]", 0, 255);
				s_sct = 255;
			}

			if(is_set(pre_across, ACROSS_ON)) {
				clr_flag(&pre_across, ACROSS_ON);
				set_flag(&pre_across, HAVE_ACROSS_ON);
				out_len = sprintf(buf, "[\\x%x-\\x%x]", s_sct, 255);
				s_sct = 255;
			}

			ret = ana_ip(s_next_ptr + 1, d_next_ptr + 1, buf + out_len, proc_num-1, pre_across, mode, buf_head);
			*(buf + out_len) = 0;
			if(ret == -1) 	return -1;

			if(is_set(pre_across, ACROSS_BEGIN)) {
				clr_flag(&pre_across, ACROSS_BEGIN);
				set_flag(&pre_across, ACROSS_ON);
			}
			s_sct++;
		}
		return 0;
	}

	set_flag(&global_cross, GLOBAL_ACROSS_BEGIN);
	set_flag(&pre_across, ACROSS_BEGIN);

	if(mode == 1) {
		pre_across = 0;
		set_flag(&pre_across, ACROSS_ON);
		s_sct = 0;
		mode = 0;
	}

	/* first s_sct must smaller than d_sct */
	while(s_sct <= d_sct) {
		if(s_sct == d_sct) {
			out_len = sprintf(buf, "\\x%x", s_sct);
			global_cross = 0;
			mode = 1;
		}

		if(is_set(pre_across, ACROSS_BEGIN)) {
			if(proc_num != 1) {
				out_len = sprintf(buf, "\\x%x", s_sct);
			} else {
				out_len = sprintf(buf, "[\\x%x-\\x%x]", s_sct, d_sct);
				s_sct = d_sct;
			}
		}

		if(is_set(pre_across, ACROSS_ON)) {
			if(proc_num != 1) {
				clr_flag(&pre_across, ACROSS_ON);
				set_flag(&pre_across, HAVE_ACROSS_ON);
				out_len = sprintf(buf, "[\\x%x-\\x%x]", s_sct, d_sct-1);
				s_sct = d_sct-1;
			} else {
				out_len = sprintf(buf, "[\\x%x-\\x%x]", s_sct, d_sct);
				s_sct = d_sct;
			}
		}

		ret = ana_ip(s_next_ptr + 1, d_next_ptr + 1, buf + out_len, proc_num-1, pre_across, mode, buf_head);
		*(buf + out_len) = 0;
		if(ret == -1)	return -1;

		if(is_set(pre_across, HAVE_ACROSS_ON)) {
			clr_flag(&pre_across, HAVE_ACROSS_ON);
		}

		if(is_set(pre_across, ACROSS_BEGIN)) {
			clr_flag(&pre_across, ACROSS_BEGIN);
			set_flag(&pre_across, ACROSS_ON);
		}
		s_sct++;
	}
	return 0;
}

int analyse_ip(char *sip, char *dip, int proc_num)
{
	char *buf = malloc((11 * proc_num) + 1);
	if(buf == NULL)
		return -1;
	int ret = ana_ip(sip, dip, buf, proc_num, 0, 0, buf);
	free(buf);
	return ret;
}

int main()
{
	char *sip="192.168.10.2.2.3.45.51.00.2";
	char *dip="192.168.77.2.3.5.6.4.10.5";
	int ret = analyse_ip(sip, dip, 10);
	if(ret == -1)
		printf("input err\n");
}
